﻿/*------------------------------------------------------------------------

SMART_STRING.HPP v3.4

Copyright 楊志賢 CxxlMan, 2008 - 2012
All Rights Reserved


------------------------------------------------------------------------*/

#if !defined(__SMART_STRING_HPP_CxxlMan)
#define __SMART_STRING_HPP_CxxlMan

#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include "SMART_PTR.HPP"


#if defined(_CXXLOBJECT_DLLEXPORT)
#define CXXLOBJECT_DLLEXPORT CXXL_DLLEXPORT
#else
#define CXXLOBJECT_DLLEXPORT CXXL_DLLIMPORT
#endif

namespace CxxlMan
{

class MB_String;
class UNICODE_String;

inline const UNICODE_String operator +(const UNICODE_String &U_Str1, const UNICODE_String &U_Str2);
inline const MB_String operator +(const MB_String &M_Str1, const MB_String &M_Str2);
inline const UNICODE_String operator +(const UNICODE_String &U_Str, const MB_String &M_Str);
inline const MB_String operator +(const MB_String &M_Str, const UNICODE_String &U_Str);


template <typename T>
class string_wrapper:virtual public cxxlObject
{
  const T *m_str;

  // Constructor
  string_wrapper(const T *str,ISpirit *spirit)
    :cxxlObject(spirit)
  {
    m_str = str;
  }
public:

  // Destructor
  virtual ~string_wrapper()
  {
    delete [] m_str;
  }

  cxxlFASTCALL operator const T*() const
  {
    return m_str;
  }

  friend class MB_String;
  friend class UNICODE_String;
  friend inline const UNICODE_String operator +(const UNICODE_String &U_Str1, const UNICODE_String &U_Str2);
  friend inline const MB_String operator +(const MB_String &M_Str1, const MB_String &M_Str2);
};

class CXXLOBJECT_DLLEXPORT MB_String:public Smart_Ptr<string_wrapper<char> >
{
  const char *cxxlFASTCALL Copy(const char *src)
  {
    if(src == NULL)
	  return NULL;
    size_t len=strlen(src)+1;
    char *tmp = new char[len];
    strcpy(tmp,src);
    return tmp;
  }

  string_wrapper<char> *Create_string_wrapper(const char *src, ISpirit *spirit)
  {
    const char *tmp = Copy(src);
    if(tmp == NULL)
      return NULL;
    return new string_wrapper<char>(tmp, spirit);
  }

  // wcs to mbs
  const char *cxxlFASTCALL Convert(const wchar_t *wcs)
  {
    if(wcs == NULL)
	  return NULL;
    size_t len = MB_CUR_MAX * wcslen(wcs) + 1;
    char *tmp = new char[len];

    if(wcstombs(tmp, wcs, len) == (size_t)-1)
      *tmp = '\0';

    return tmp;
  }

  const char *cxxlFASTCALL CreateSpace(size_t Count)
  {
    return new char[Count];
  }



public:
  // Constructor，空字串
  MB_String()
    :Smart_Ptr(NULL, rootObject)
  {
  }

  // Constructor
  MB_String(const char *str, ISpirit *spirit = Spirit_Easy)
    :Smart_Ptr(Create_string_wrapper(str, spirit), rootObject)
  {
  }

  // Constructor，指定未初始的空間
  MB_String(size_t Count, ISpirit *spirit = Spirit_Easy)
    :Smart_Ptr(new string_wrapper<char>(CreateSpace(Count),spirit), rootObject)
  {
  }


  // Constructor，wcs to mbs
  MB_String(const UNICODE_String &wcs, ISpirit *spirit = Spirit_Easy);

  // Constructor
  MB_String(string_wrapper<char> *pStr_Wrapper)
    :Smart_Ptr(pStr_Wrapper,rootObject)
  {
  }

  // Copy Constructor
  MB_String(const MB_String &Src)
    :Smart_Ptr((string_wrapper<char> *)Src,rootObject)
  {
  }

  // Destructor
  virtual ~MB_String()
  {
  }


  // 設定函數
  MB_String& cxxlFASTCALL operator =(string_wrapper<char> *pStr_Wrapper)
  {
    Smart_Ptr<string_wrapper<char> >::operator =(pStr_Wrapper);
    return *this;
  }

  // 設定函數，wcs to mbs
  MB_String& cxxlFASTCALL operator =(const UNICODE_String &wcs);

  // 轉形
  cxxlFASTCALL operator const char*() const
  {
    return (const char*) *((string_wrapper<char> *)*this);
  }

  char &cxxlFASTCALL operator [](int Index)
  {
    char *p = (char *)(const char*)*this;
    return *(p+Index);
  }

  char cxxlFASTCALL operator [](int Index) const
  {
    char *p = (char *)(const char*)*this;
    return *(p+Index);
  }


  // 字串長度
  size_t cxxlFASTCALL StrLength(void)  const
  {
    return strlen(*this);
  }


  // 增加字串
  void cxxlFASTCALL operator +=(const MB_String &mbs)
  {
    MB_String temp = *this + mbs;
    *(Smart_Ptr<string_wrapper<char> >*)this = temp;
  }

  // 增加字串
  void cxxlFASTCALL operator +=(const UNICODE_String &wcs)
  {
    MB_String temp = *this + wcs;
    *(Smart_Ptr<string_wrapper<char> >*)this = temp;
  }

};


class CXXLOBJECT_DLLEXPORT UNICODE_String:public Smart_Ptr<string_wrapper<wchar_t> >
{
  const wchar_t *cxxlFASTCALL Copy(const wchar_t *src)
  {
    if(src == NULL)
      return NULL;
    size_t len=wcslen(src)+1;
    wchar_t *tmp = new wchar_t[len];
    wcscpy(tmp,src);
    return tmp;
  }

  string_wrapper<wchar_t> *Create_string_wrapper(const wchar_t *src, ISpirit *spirit)
  {
    const wchar_t *tmp = Copy(src);
    if(tmp == NULL)
      return NULL;
    return new string_wrapper<wchar_t>(tmp, spirit);
  }

  // mbs to wcs
  const wchar_t *cxxlFASTCALL Convert(const char *mbs)
  {
    if(mbs == NULL)
      return NULL;
    size_t len = strlen(mbs) + 1;
    wchar_t *tmp = new wchar_t[len];

    if(mbstowcs(tmp, mbs, len) == (size_t)-1)
      *tmp = L'\0';

    return tmp;
  }

  const wchar_t *cxxlFASTCALL CreateSpace(size_t Count)
  {
    return new wchar_t[Count];
  }


public:
  // Constructor，空字串
  UNICODE_String()
    :Smart_Ptr(NULL, rootObject)
  {
  }

  // Constructor
  UNICODE_String(const wchar_t *str, ISpirit *spirit = Spirit_Easy)
    :Smart_Ptr(Create_string_wrapper(str, spirit), rootObject)
  {
  }

  // Constructor，指定未初始的空間
  UNICODE_String(size_t Count, ISpirit *spirit = Spirit_Easy)
    :Smart_Ptr(new string_wrapper<wchar_t>(CreateSpace(Count),spirit), rootObject)
  {
  }

  // Constructor,mbs to wcs
  UNICODE_String(const MB_String &mbs, ISpirit *spirit = Spirit_Easy);

/*
  // Constructor,mbs to wcs
  UNICODE_String(const string_wrapper<char> *pmbs_wrapper, cxxlObject *Host = rootObject, ISpirit *spirit = Spirit_Easy)
    :Smart_Ptr((pmbs_wrapper == NULL)? NULL:new string_wrapper<wchar_t>(Convert(*pmbs_wrapper),spirit),
               Host)
  {
  }
*/

  // Constructor
  UNICODE_String(string_wrapper<wchar_t> *pStr_Wrapper)
    :Smart_Ptr(pStr_Wrapper,rootObject)
  {
  }

  // Copy Constructor
  UNICODE_String(const UNICODE_String &Src)
    :Smart_Ptr((string_wrapper<wchar_t> *)Src,rootObject)
  {
  }

  // Destructor
  virtual ~UNICODE_String()
  {
  }

  // 設定函數
  UNICODE_String& cxxlFASTCALL operator =(string_wrapper<wchar_t> *pStr_Wrapper)
  {
    Smart_Ptr<string_wrapper<wchar_t> >::operator =(pStr_Wrapper);
    return *this;
  }

  // 設定函數,mbs to wcs
  UNICODE_String& cxxlFASTCALL operator =(const MB_String &mbs);

  // 轉形
  cxxlFASTCALL operator const wchar_t*() const
  {
    return (const wchar_t*) *((string_wrapper<wchar_t> *)*this);
  }

  wchar_t &cxxlFASTCALL operator [](int Index)
  {
    wchar_t *p = (wchar_t *)(const wchar_t*)*this;
    return *(p+Index);
  }

  wchar_t cxxlFASTCALL operator [](int Index) const
  {
    wchar_t *p = (wchar_t *)(const wchar_t*)*this;
    return *(p+Index);
  }

  // 字串長度
  size_t cxxlFASTCALL StrLength(void)  const
  {
    return wcslen(*this);
  }


  // 增加字串
  void cxxlFASTCALL operator +=(const UNICODE_String &wcs)
  {
    UNICODE_String temp = *this + wcs;
    *(Smart_Ptr<string_wrapper<wchar_t> >*)this = temp;
  }

  // 增加字串
  void cxxlFASTCALL operator +=(const MB_String &mbs)
  {
    UNICODE_String temp = *this + mbs;
    *(Smart_Ptr<string_wrapper<wchar_t> >*)this = temp;
  }

};

// ==
inline bool operator ==(const wchar_t *str,const UNICODE_String &U_Str)
{
  return wcscmp(str, (const wchar_t*)U_Str) == 0;
}
inline bool operator ==(const UNICODE_String &U_Str, const wchar_t *str)
{
  return wcscmp(str, (const wchar_t*)U_Str) == 0;
}
inline bool operator ==(const UNICODE_String &U_Str1,const UNICODE_String &U_Str2)
{
  return wcscmp((const wchar_t*)U_Str1, (const wchar_t*)U_Str2) == 0;
}

inline bool operator ==(const char *str, const MB_String &M_Str)
{
  return strcmp(str, (const char*)M_Str) == 0;
}
inline bool operator ==(const MB_String &M_Str, const char *str)
{
  return strcmp(str, (const char*)M_Str) == 0;
}
inline bool operator ==(const MB_String &M_Str1,const MB_String &M_Str2)
{
  return strcmp((const char*)M_Str1, (const char*)M_Str2) == 0;
}


// !=
inline bool operator !=(const wchar_t *str, const UNICODE_String &U_Str)
{
  return !(str == U_Str);
}
inline bool operator !=(const UNICODE_String &U_Str, const wchar_t *str)
{
  return !(str == U_Str);
}
inline bool operator !=(const UNICODE_String &U_Str1, const UNICODE_String &U_Str2)
{
  return !(U_Str1 == U_Str2);
}

inline bool operator !=(const char *str, const MB_String &M_Str)
{
  return !(str == M_Str);
}
inline bool operator !=(const MB_String &M_Str, const char *str)
{
  return !(str == M_Str);
}
inline bool operator !=(const MB_String &M_Str1, const MB_String &M_Str2)
{
  return !(M_Str1 == M_Str2);
}


// >
inline bool operator >(const wchar_t *str, const UNICODE_String &U_Str)
{
  return wcscmp(str, (const wchar_t*)U_Str) > 0;
}
inline bool operator >(const UNICODE_String &U_Str, const wchar_t *str)
{
  return wcscmp((const wchar_t*)U_Str, str) > 0;
}
inline bool operator >(const UNICODE_String &U_Str1, const UNICODE_String &U_Str2)
{
  return wcscmp((const wchar_t*)U_Str1, (const wchar_t*)U_Str2) > 0;
}

inline bool operator >(const char *str, const MB_String &M_Str)
{
  return strcmp(str, (const char*)M_Str) > 0;
}
inline bool operator >(const MB_String &M_Str, const char *str)
{
  return strcmp((const char*)M_Str, str) > 0;
}
inline bool operator >(const MB_String &M_Str1, const MB_String &M_Str2)
{
  return strcmp((const char*)M_Str1, (const char*)M_Str2) > 0;
}


// <
inline bool operator <(const wchar_t *str, const UNICODE_String &U_Str)
{
  return wcscmp(str, (const wchar_t *)U_Str) < 0;
}
inline bool operator <(const UNICODE_String &U_Str, const wchar_t *str)
{
  return wcscmp((const wchar_t *)U_Str, str) < 0;
}
inline bool operator <(const UNICODE_String &U_Str1, const UNICODE_String &U_Str2)
{
  return wcscmp((const wchar_t *)U_Str1, (const wchar_t *)U_Str2) < 0;
}

inline bool operator <(const char *str, const MB_String &M_Str)
{
  return strcmp(str, (const char*)M_Str) < 0;
}
inline bool operator <(const MB_String &M_Str, const char *str)
{
  return strcmp((const char *)M_Str, str) < 0;
}
inline bool operator <(const MB_String &M_Str1, const MB_String &M_Str2)
{
  return strcmp((const char *)M_Str1, (const char *)M_Str2) < 0;
}


// >=
inline bool operator >=(const wchar_t *str, const UNICODE_String &U_Str)
{
  return !(wcscmp(str, (const wchar_t *)U_Str) < 0);
}
inline bool operator >=(const UNICODE_String &U_Str, const wchar_t *str)
{
  return !(wcscmp((const wchar_t *)U_Str, str) < 0);
}
inline bool operator >=(const UNICODE_String &U_Str1, const UNICODE_String &U_Str2)
{
  return !(wcscmp((const wchar_t *)U_Str1, (const wchar_t *)U_Str2) < 0);
}

inline bool operator >=(const char *str, const MB_String &M_Str)
{
  return !(strcmp(str, (const char *)M_Str) < 0);
}
inline bool operator >=(const MB_String &M_Str, const char *str)
{
  return !(strcmp((const char *)M_Str, str) < 0);
}
inline bool operator >=(const MB_String &M_Str1, const MB_String &M_Str2)
{
  return !(strcmp((const char *)M_Str1, (const char *)M_Str2) < 0);
}


// <=
inline bool operator <=(const wchar_t *str, const UNICODE_String &U_Str)
{
  return !(wcscmp(str, (const wchar_t *)U_Str) > 0);
}
inline bool operator <=(const UNICODE_String &U_Str, const wchar_t *str)
{
  return !(wcscmp((const wchar_t *)U_Str, str) > 0);
}
inline bool operator <=(const UNICODE_String &U_Str1, const UNICODE_String &U_Str2)
{
  return !(wcscmp((const wchar_t *)U_Str1, (const wchar_t *)U_Str2) > 0);
}

inline bool operator <=(const char *str, const MB_String &M_Str)
{
  return !(strcmp(str, (const char *)M_Str) > 0);
}
inline bool operator <=(const MB_String &M_Str, const char *str)
{
  return !(strcmp((const char *)M_Str, str) > 0);
}
inline bool operator <=(const MB_String &M_Str1, const MB_String &M_Str2)
{
  return !(strcmp((const char *)M_Str1, (const char *)M_Str2) > 0);
}


// 字串連結
inline const UNICODE_String operator +(const UNICODE_String &U_Str1, const UNICODE_String &U_Str2)
{
  wchar_t *temp;

  size_t len = U_Str1.StrLength() + U_Str2.StrLength() + 1;
  temp = new wchar_t[len];
  wcscpy(temp,(const wchar_t *)U_Str1);
  wcscat(temp,(const wchar_t *)U_Str2);

  return UNICODE_String(temp,U_Str1->GetSpirit());
}

inline const MB_String operator +(const MB_String &M_Str1, const MB_String &M_Str2)
{
  char *temp;

  size_t len = M_Str1.StrLength() + M_Str2.StrLength() + 1;
  temp = new char[len];
  strcpy(temp,(const char *)M_Str1);
  strcat(temp,(const char *)M_Str2);

  return MB_String(temp,M_Str1->GetSpirit());
}

inline const UNICODE_String operator +(const UNICODE_String &U_Str, const MB_String &M_Str)
{
  UNICODE_String temp(M_Str);
  return U_Str+temp;
}

inline const MB_String operator +(const MB_String &M_Str, const UNICODE_String &U_Str)
{
  MB_String temp(U_Str);
  return M_Str+temp;
}


}
#endif
